import numpy as np
import matplotlib.pyplot as mp
import part1 as p1
import numpy.linalg as lg
mp.clf()



#-- Malthus --#

def malthus(gamma):
    def f(y,t):
        return gamma*y[0]
    
    return [f]

def plot_malthus(gamma_init,gamma_final,nbre_courbes,y0,t0,tf,eps):
    
    for i in np.arange(0,nbre_courbes,1):
        gamma = gamma_init + i*(gamma_final - gamma_init)/nbre_courbes
        f = malthus(gamma)
        Y = p1.meth_epsilon(y0,t0,tf,eps,f,p1.runge_kutta_step)[0]
        X = np.linspace(t0,tf,Y.shape[0])
        a = mp.plot(X,Y)
        
        
    
plot_malthus(-0.5,0.2,10,np.array([10.]),0.,20.,0.05)
mp.title('Methode de Malthus pour differents $\gamma$')
mp.xlabel('temps')
mp.ylabel('population')
mp.savefig('Methode_de_Malthus_pour_differents_gamma.png')

mp.clf()


f1 = malthus(-1)
f2 = malthus(0)
f3 = malthus(1)

Y1=p1.meth_epsilon(np.array([10.]),0.,10.,0.05,f1,p1.runge_kutta_step)[0]
Y2=p1.meth_epsilon(np.array([10.]),0.,10.,0.05,f2,p1.runge_kutta_step)[0]
Y3=p1.meth_epsilon(np.array([10.]),0.,10.,0.05,f3,p1.runge_kutta_step)[0]


X1 = np.linspace(0.,10.,Y1.shape[0])
X2 = np.linspace(0.,10.,Y2.shape[0])
X3 = np.linspace(0.,10.,Y3.shape[0])


mp.axis([0.,10.,0.,150.])
ax = mp.gca()
ax.set_autoscale_on(False)


r1 = mp.plot(X1,Y1)
r2 = mp.plot(X2,Y2)
r3 = mp.plot(X3,Y3)

mp.title("Methode de Malthus pour differents $\gamma$")
mp.xlabel("temps")
mp.ylabel("population")
mp.legend((r1,r2,r3),("$\gamma$ = -1","$\gamma$ = 0","$\gamma$ = 1"))
mp.savefig("methode_malthus.png")

mp.clf()


#-- Verhulst --#


def verhulst(gamma,k):
    def f(y,t):
        return gamma*y[0]*(1-y[0]/k)
    return [f]


def plot_verhulst_varier_gamma(gamma_init,gamma_final,k_fixe,nbre_courbes,y0,t0,tf,nbpas):
    
    for i in np.arange(0,nbre_courbes,1):
        f = verhulst(gamma_init + i*(gamma_final - gamma_init)/nbre_courbes,k_fixe)
        Y = p1.meth_step_n(y0,t0,nbpas,(tf-t0)/nbpas,f,p1.runge_kutta_step)[0]
        
        X = np.linspace(t0,tf,Y.shape[0])
        mp.plot(X,Y)

plot_verhulst_varier_gamma(0.5,2,30,10,np.array([10.]),0.,20.,1000)

mp.title('Methode de Verhulst pour differents $\gamma$ et k = 30')
mp.xlabel('temps')
mp.ylabel('population')
mp.savefig('Methode_de_Verhulst_pour_differents_gamma.png')


def plot_verhulst_varier_k(gamma_fixe,k_init,k_final,nbre_courbes,y0,t0,tf,nbpas):
    
    for i in np.arange(0,nbre_courbes,1):
        f = verhulst(gamma_fixe, k_init + i*(k_final - k_init)/nbre_courbes)
        Y = p1.meth_step_n(y0,t0,nbpas,(tf-t0)/nbpas,f,p1.runge_kutta_step)[0]
     
        X = np.linspace(t0,tf,Y.shape[0])
        mp.plot(X,Y)

mp.clf()
plot_verhulst_varier_k(2.,10,30,10,np.array([10.]),0.,20.,1000)

mp.title('Methode de Verhulst pour differents k et $\gamma$ = 2')
mp.xlabel('temps')
mp.ylabel('population')
mp.savefig('Methode_de_Verhulst_pour_differents_k.png')
#-- methode de verhulst avec des valeurs specifiques ---#
mp.clf()
f1 = verhulst(0.5,30)
f2 = verhulst(1,30)
f3 = verhulst(2,30)



Y1=p1.meth_epsilon(np.array([10.]),0.,10.,0.05,f1,p1.step_point_milieu)[0]
Y2=p1.meth_epsilon(np.array([10.]),0.,10.,0.05,f2,p1.step_point_milieu)[0]
Y3=p1.meth_epsilon(np.array([10.]),0.,10.,0.05,f3,p1.step_point_milieu)[0]






X1 = np.linspace(0.,10.,Y1.shape[0])
X2 = np.linspace(0.,10.,Y2.shape[0])
X3 = np.linspace(0.,10.,Y3.shape[0])


mp.axis([0.,10.,10.,30.])

ax = mp.gca()
ax.set_autoscale_on(False)


r1 = mp.plot(X1,Y1)
r2 = mp.plot(X2,Y2)
r3 = mp.plot(X3,Y3)

mp.title("Methode de verhulst pour differents $\gamma$ et avec k=30")
mp.xlabel("temps")
mp.ylabel("population")
mp.legend((r1,r2,r3),("$\gamma$ = 0.5","$\gamma$ = 1","$\gamma$ = 2"))
mp.savefig("methode cerhulust.png")

mp.clf()


#-- Lotka-Volterra --#

def lotka_volterra(a,b,c,d):
    def N(y,t):
        return y[0]*(a-b*y[1])
    def P(y,t):
        return y[1]*(c*y[0]-d)
    return [N,P]

#--- Test de Lotka-Volterra ---#

L = lotka_volterra(0.4,0.25,0.4,0.2)

Y = p1.meth_step_n(np.array([8.,4.]),0.,10000,0.1,L,p1.runge_kutta_step)[0]
X = np.linspace(0.,1000.,Y.shape[0])
n = X.shape[0]

Y1 = p1.extract_abcissas(Y,n)
Y2 = p1.extract_ordinates(Y,n)


mp.clf()
mp.title("Modele de Lotka-Volterra avec a=c=0.4, b=0.25 et d=0.2")
mp.xlabel("axe temporelle")
mp.ylabel("N(t), P(t)")

a = mp.plot(X,Y1)
b = mp.plot(X,Y2)
mp.legend((a,b),("Proies","Predateur"))
mp.savefig("methode_lotka_volterra.png")
mp.clf()
mp.title("Evolution des Proies en fonction des predateurs")
mp.xlabel("N(t)")
mp.ylabel("P(t)")
mp.plot(Y1,Y2)
mp.savefig("methode_lokta_N_P.png")



#-- Calcul de la periode des solutions --#

def calcul_periode(N, P, ti, pas, eps):
    Ni = N[0]
    Pi = P[0]
    t = ti
    i = 1
    
    
    
    while(lg.norm(N[i] - Ni) < eps and lg.norm(P[i] - Pi) < eps):
        t = t + pas
        
    return t - ti

L = lotka_volterra(0.4,0.25,0.4,0.2)

Y = p1.meth_step_n(np.array([8.,4.]),0.,10000,0.1,L,p1.runge_kutta_step)[0]
X = np.linspace(0.,1000.,Y.shape[0])
n = X.shape[0]

Y1 = p1.extract_abcissas(Y,n)
Y2 = p1.extract_ordinates(Y,n)
print Y1
print Y2
print "la periode du modele lotka_volterra dans le cas a=c=0.4, b=0.25 et d=0.2 \n"
print calcul_periode(Y1,Y2,0.,0.1,0.5)


